#pragma once
#include <cstdint>
#include <iostream>
#include <ostream>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<cstdio>
#include<string>
#include<unistd.h>
#include<string.h>
#include<unordered_map>

class UdpServer
{
public: 
    UdpServer(uint16_t port,std::string ip="")
    :_sock(-1)
    ,_ip(ip)
    ,_port(port)
    {

    }
    bool initServer()
    {
        _sock=socket(AF_INET,SOCK_DGRAM,0);
        if(_sock < 0)
        {
            std::cout<<"socket() failed"<<std::endl;
            exit(1);
        }
        struct sockaddr_in server;
        bzero(&server,sizeof(server));
        server.sin_family=AF_INET;
        server.sin_port=htons(_port);
        server.sin_addr.s_addr=_ip.empty()?INADDR_ANY:inet_addr(_ip.c_str());
        if(bind(_sock,(struct sockaddr*)&server,sizeof(server)) < 0)
        {
            std::cout<<"bind() failed"<<std::endl;
            exit(2);
        }
        return true;
    }
    // void start()
    // {
    //     char buffer[1024];
    //     while(true)
    //     {
    //         struct sockaddr_in client;
    //         socklen_t len=sizeof(client);
    //         char key[64];
    //         ssize_t s=recvfrom(_sock,buffer,sizeof(buffer),0,(struct sockaddr*)&client,&len);
    //         if(s > 0)
    //         {
    //             std::string message=key;
    //             message+="#";
    //             message+=buffer;
    //             sendto(_sock,message.c_str(),message.size(),0,(struct sockaddr*)&client,len);
    //         }
    //     }
    // }
    void start()
    {
        char buffer[1024];
        while(true)
        {
            struct sockaddr_in client;
            char key[64];
            socklen_t len=sizeof(client);
            ssize_t s=recvfrom(_sock,buffer,sizeof(buffer),0,(struct sockaddr*)&client,&len);
            if(s > 0)
            {
                //根据收到的消息确定客户端的地址结构，并入用户表
                std::string client_ip=inet_ntoa(client.sin_addr);
                uint16_t client_port=ntohs(client.sin_port);
                snprintf(key,sizeof(key),"%s-%u",client_ip.c_str(),client_port);
                auto it=_users.find(key);
                if(it==_users.end())
                {
                    _users.insert({key,client});
                }
            }
            for(auto& iter:_users){
                std::string message=key;
                message+="#";
                message+=buffer;
                sendto(_sock,buffer,sizeof(buffer),0,(struct sockaddr*)&client,len);
            }
        }
    }
    ~UdpServer(){
        if(_sock < 0){
            close(_sock);
        }
    }
private:
    std::string _ip;
    uint16_t _port;
    int _sock;
    std::unordered_map<std::string,struct sockaddr_in> _users;
};
// class UdpServer
// {
// public:
//     UdpServer(uint16_t port,std::string ip="")
//     :_sock(-1)
//     ,_port(port)
//     ,_ip(ip)
//     {

//     }
//     void initServer()
//     {
//         _sock=socket(AF_INET,SOCK_DGRAM,0);
//         if(_sock < 0)
//         {
//             std::cout<<"socket() failed"<<std::endl;
//             exit(1);
//         }
//         struct sockaddr_in server;
//         bzero(&server,sizeof(server));
//         server.sin_port=htons(_port);
//         server.sin_family=AF_INET;
//         server.sin_addr.s_addr=_ip.empty()?INADDR_ANY:inet_addr(_ip.c_str());
        
//         if(bind(_sock,(struct sockaddr*)&server,sizeof(server)) < 0)
//         {
//             std::cout<<"socket() failed"<<std::endl;
//             exit(2);
//         }
//     }
//     // void start()
//     // {
//     //     std::string buffer;
//     //     struct sockaddr_in client;
//     //     bzero(&client,sizeof(client));
//     //     while(true)
//     //     {
//     //         std::uint16_t client_port=htons(client.sin_port);
//     //         std::string client_ip=inet_addr(client.sin_addr);
//     //     }
//     // }
//     //线程要开始执行任务了
//     void start()
//     {
//         char buffer[1024];
//         while(true)
//         {
//             struct sockaddr_in client;
//             char key[64];
//             socklen_t len=sizeof(client);
//             ssize_t s=recvfrom(_sock,buffer, sizeof(buffer),0,(struct sockaddr*)&client,&len);
//             if(s > 0)
//             {
//                 buffer[s]=0;
//                 uint16_t clientport=ntohs(client.sin_port);
//                 std::string clientip=inet_ntoa(client.sin_addr);
//                 snprintf(key,sizeof(key),"%s-%u",clientip.c_str(),clientport);
//                 auto it=_users.find(key);
//                 if(it==_users.end()){
//                     _users.insert({key,client});
//                 }
//             }
//             for(auto& iter:_users)
//             {
//                 std::string message=key;
//                 message+="#";
//                 message+=buffer;
//                 sendto(_sock,message.c_str(),message.size(),0,(struct sockaddr*)&client,sizeof(client));
//             }
//         }
//     }
//     ~UdpServer(){
//         if(_sock < 0){
//             close(_sock);
//         }
//     }
// private:
//     uint16_t _port;
//     std::string _ip;
//     int _sock;
//     std::unordered_map<std::string ,struct sockaddr_in> _users;
// };
// class UdpServer
// {
// public:
//     UdpServer(uint16_t port,std::string ip)
//     :_port(port)
//     ,_ip(ip)
//     ,_sock(-1)
//     {}
//     void initServer()
//     {
//         _sock=socket(AF_INET,SOCK_DGRAM,0);
//         if(_sock < 0)
//         {
//             std::cout<<"socket() failed"<<std::endl;
//             exit(1);
//         }
//         struct sockaddr_in server;
//         bzero(&server,sizeof(server));
//         server.sin_family=AF_INET;
//         server.sin_port=htons(_port);
//         server.sin_addr.s_addr=_ip.empty()?INADDR_ANY:inet_addr(_ip.c_str());
//         if(bind(_sock,(struct sockaddr*)&server,sizeof(server)) < 0)
//         {
//             std::cout<<"bind() failed"<<std::endl;
//             exit(2);
//         }
//     }
//     void start()
//     {
//         char buffer[1024];
//         while(true)
//         {
//             struct sockaddr_in client;
//             char key[64];
//             socklen_t len=sizeof(client);
//             ssize_t s=recvfrom(_sock,buffer,sizeof(buffer),0,
//             (struct sockaddr*)&client,&len);
//             if(s > 0)
//             {
//                 buffer[s]=0;
//                 std::string client_ip=inet_ntoa(client.sin_addr);
//                 uint16_t client_port=ntohs(client.sin_port);
//                 snprintf(key,sizeof(key),"%s-%u",client_ip.c_str(),client_port);
//                 auto it=_users.find(key);
//                 if(it==_users.end()){
//                     _users.insert({key,client});
//                 }
//                 for(auto& iter:_users){
//                     std::string message=key;
//                     message+="#";
//                     message+=buffer;
//                     sendto(_sock,message.c_str(),sizeof(buffer),0,
//                     (struct sockaddr*)&client,len);
//                 }
//             }
//         }
//     }
//     ~UdpServer(){
//         if(_sock < 0){
//             close(_sock);
//         }
//     }
// private:
//     std::string _ip;
//     uint16_t _port;
//     int _sock;
//     std::unordered_map<std::string, struct sockaddr_in> _users;
// };
// class UdpServer
// {
// public:
//     UdpServer(uint16_t port,std::string ip="")
//     :_sock(-1)
//     ,_port(port)
//     ,_ip(ip)
//     {

//     }
//     void initServer()
//     {
//         _sock=socket(AF_INET,SOCK_DGRAM,0);
//         if(_sock < 0)
//         {
//             std::cout<<"socket() failed"<<std::endl;
//             exit(1);
//         }
//         struct sockaddr_in server;
//         bzero(&server,sizeof(server));
//         server.sin_family=AF_INET;
//         server.sin_port=htons(_port);
//         server.sin_addr.s_addr=_ip.empty()?INADDR_ANY:inet_addr(_ip.c_str());
//         if(bind(_sock,(struct sockaddr*)&server, sizeof(server)) < 0)
//         {
//             std::cout<<"bind() failed"<<std::endl;
//             exit(3);
//         }
//     }
//     void start()
//     {
//         char buffer[1024];
//         while(true)
//         {
//             struct sockaddr_in client;
//             char key[64];
//             socklen_t len=sizeof(client);
//             ssize_t s=recvfrom(_sock,buffer,sizeof(buffer),0,(struct sockaddr*)&client, &len);
//             if(s > 0)
//             {
//                 buffer[s]=0;
//                 std::string clientip=inet_ntoa(client.sin_addr);
//                 uint16_t clientport=ntohs(client.sin_port);
//                 snprintf(key,sizeof(key),"%s-%u",clientip.c_str(),clientport);
//                 auto it=_users.find(key);
//                 if(it==_users.end()){
//                     _users.insert({key,client});
//                 }
//                 for(auto& iter:_users){
//                     std::string message=key;
//                     message+="#";
//                     message+=buffer;
//                     sendto(_sock,buffer,sizeof(buffer),0,(struct sockaddr*)&client,len);
//                 }
//             }
//         }
//     }
//     ~UdpServer(){
//         if(_sock<0){
//             close(_sock);
//         }
//     }
// private:
//     int _sock;
//     std::string _ip;
//     uint16_t _port;
//     std::unordered_map<std::string, struct sockaddr_in> _users;
// };
